package com.xzz.mybatis.generator.dcevm.service;


import com.xzz.mybatis.generator.dcevm.MyDynamicCodeAgent;
import com.xzz.mybatis.generator.dcevm.dto.MyDynamicCodeMessageDTO;
import com.xzz.mybatis.generator.dcevm.fo.MyDynamicCodeFO;
import com.xzz.mybatis.generator.utils.MyFileUtil;
import com.xzz.mybatis.generator.utils.MyStringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.RandomAccessFile;
import java.lang.instrument.ClassDefinition;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;

/**
 * Created on 2020/12/2.
 *
 * @author 朱智贤
 */
@Slf4j
@Component
public class MyDynamicCodeHelper {

//    @Resource
//    private EpRocketMqTemplate rocketMqTemplate;

    private static final String APP_NAME_KEY = "my.appName";

    /** 上传文件并发送消息 */
    public void doUploadAndSendBusMsg(MultipartFile file, MyDynamicCodeFO dynamicCodeFO) {
        MyDynamicCodeMessageDTO messageDTO = new MyDynamicCodeMessageDTO(dynamicCodeFO.getFullClassName(),null, dynamicCodeFO.getAppName());
        this.consumeDynamicCodeMessage(file,messageDTO);
    }

    /** 消费动态代码消息 */
//    @EpRocketMqConsumerMethod(groupName = EpMqConsumerGroupName.FMS_DCEVM_GROUP,
//            topic = EpMqTopic.FMS_DCEVM_TOPIC, consumeMode = EpConsumeMode.CONCURRENTLY, messageModel = MessageModel.BROADCASTING)
    public void consumeDynamicCodeMessage(MultipartFile file,MyDynamicCodeMessageDTO messageDTO){
        /**rocketMqTemplate.checkDuplicateMsg(messageDTO);*/ //因为是广播消息, 所以不需要检查消息是否重复发送了
        log.warn("收到动态代码替换信息 类 {} 下载地址 {}", messageDTO.getFullClassName(), messageDTO.getClassOssUrl());

//        if(!System.getProperty(APP_NAME_KEY).equals(messageDTO.getAppName())){
//            log.warn("非本应用热部署消息 当前应用名称 {} 需要部署应用名称 {}", System.getProperty(APP_NAME_KEY), messageDTO.getAppName());
//            return;
//        }


        String hostname = null;
        String classSimpleName = messageDTO.getFullClassName().substring(messageDTO.getFullClassName().lastIndexOf('.'),
                messageDTO.getFullClassName().length());
        //文件下载回本地
//        File tmpFile = EpFileUtil.downloadOSSFileToTmpDir(messageDTO.getClassOssUrl().substring(EpFileUtil.getOssDownloadDomain().length()+1),
//                classSimpleName + FileSuffixType.CLASS.getDesc());
        File tmpFile = MyFileUtil.writeMultipartFileToTmpDir(file);

        try (RandomAccessFile rFile = new RandomAccessFile(tmpFile, "r")){
            hostname = InetAddress.getLocalHost().getHostName().replaceAll("\\.","-");

            final byte[] bytes = new byte[(int) rFile.length()];
            rFile.readFully(bytes);

            //找类
            List<ClassDefinition> definitions = new ArrayList<>();
            for (Class<?> clazz : MyDynamicCodeAgent.getInstrumentation().getAllLoadedClasses()) {
                if(messageDTO.getFullClassName().equals(clazz.getName())){
                    definitions.add(new ClassDefinition(clazz, bytes));
                }
            }
            if(definitions.isEmpty()) throw new IllegalArgumentException(messageDTO.getFullClassName() + "类未找到");

            //真正开始替换
            MyDynamicCodeAgent.getInstrumentation().redefineClasses(definitions.toArray(new ClassDefinition[0]));

            System.out.println(String.format("实例id %s 热部署替换 %s 成功", hostname
                    ,messageDTO.getFullClassName()));


        }catch (Exception e){
            System.out.println(String.format("实例id %s 热部署替换 %s 失败, %s", hostname
                    ,messageDTO.getFullClassName(),MyStringUtil.stackTraceToString(e)));

        }
    }
}
